package com.yundashi.updateapputils.util

import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.util.Log
import android.widget.Toast
import com.yundashi.updateapputils.bean.AppInfo
import com.yundashi.updateapputils.listener.Md5CheckResultListener
import com.yundashi.updateapputils.listener.OnBtnClickListener
import com.yundashi.updateapputils.listener.OnInitUiListener
import com.yundashi.updateapputils.listener.UpdateDownloadListener
import com.yundashi.updateapputils.model.UiConfig
import com.yundashi.updateapputils.model.UpdateConfig
import com.yundashi.updateapputils.update.UpdateAppUtils
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
import java.io.PrintWriter

class AppUtil {

    private val TAG: String = AppUtil::class.java.simpleName

    /**
     * 下载app、安装
     */
    fun appDownload(
        apkUrl: String,
        content: String,
        title: String,
        updateConfig: UpdateConfig,
        uiConfig: UiConfig,
        downLoadListener: UpdateDownloadListener? = null,
        mad5Listener: Md5CheckResultListener? = null,
        initListener: OnInitUiListener? = null,
        btnListener: OnBtnClickListener? = null,
        updateListener: OnBtnClickListener? = null
    ) {
        UpdateAppUtils.getInstance()
            .apkUrl(apkUrl)
            .updateTitle(title)
            .updateContent(content)
            .uiConfig(uiConfig)
            .updateConfig(updateConfig)
            .setUpdateDownloadListener(downLoadListener)
            .setMd5CheckResultListener(mad5Listener)
            .setOnInitUiListener(initListener)
            .setCancelBtnClickListener(btnListener)
            .setUpdateBtnClickListener(updateListener)
            .update()
    }

    /**
     * root下静默安装
     */
    fun rootInstallApk(apkPath: String): Boolean {
        var printWriter: PrintWriter? = null
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("su")
            printWriter = PrintWriter(process.outputStream)
            printWriter.println("chmod 777 $apkPath")
            printWriter.println("export LD_LIBRARY_PATH=/vendor/lib:/system/lib")
            printWriter.println("pm install -r $apkPath")
            printWriter.flush()
            printWriter.close()
            val value = process.waitFor()
            return returnResult(value)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        } finally {
            process?.destroy()
        }
        return false
    }

    /**
     * root下启动apk
     */
    fun rootStartApk(packageName: String, activityName: String): Boolean {
        val isSuccess = false
        val cmd = "am start -n $packageName/$activityName \n"
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec(cmd)
            val value = process.waitFor()
            return returnResult(value)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        } finally {
            process?.destroy()
        }
        return isSuccess
    }

    /**
     * root下静默卸载
     */
    fun rootUninstallApk(packageName: String): Boolean {
        var printWriter: PrintWriter? = null
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("su")
            printWriter = PrintWriter(process.outputStream)
            printWriter.println("LD_LIBRARY_PATH=/vendor/lib:/system/lib ")
            printWriter.println("pm uninstall $packageName")
            printWriter.flush()
            printWriter.close()
            val value = process.waitFor()
            return returnResult(value)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        } finally {
            process?.destroy()
        }
        return false
    }

    /**
     * 判断手机是否有root权限
     */
    fun sysHasRoot(): Boolean {
        var printWriter: PrintWriter? = null
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("su")
            printWriter = PrintWriter(process.outputStream)
            printWriter.flush()
            printWriter.close()
            val value = process.waitFor()
            return returnResult(value)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        } finally {
            process?.destroy()
        }
        return false
    }

    /**
     * root下执行cmd的返回值
     */
    private fun returnResult(value: Int): Boolean {
        // 代表成功
        return when (value) {
            0 -> {
                true
            }
            1 -> { // 失败
                false
            }
            else -> { // 未知情况
                false
            }
        }
    }

    /**
     * 检查应用packageName 是否存在
     *
     * @return true:存在 ，false:不存在
     */
    fun checkPackInfo(packageName: String, context: Context): Boolean {
        var packageInfo: PackageInfo? = null
        try {
            packageInfo = context.packageManager.getPackageInfo(packageName, 0)
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return packageInfo != null
    }

    /**
     * 检测App是否是debug
     * */
    fun isApkDebugable(context: Context, packageName: String?): Boolean {
        try {
            val pkginfo =
                context.packageManager.getPackageInfo(packageName!!, PackageManager.GET_ACTIVITIES)
            if (pkginfo != null) {
                val info = pkginfo.applicationInfo
                return info.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
            }
        } catch (e: Exception) {
        }
        return false
    }


    /**
     * 根据包名获取版本号
     */
    fun getVersionCode(context: Context, packageName: String?): Int {
        val packageManager = context.packageManager
        try {
            val Info = packageManager.getPackageInfo(packageName!!, 0)
            return Info.versionCode
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 程序是否是前台
     */
    private fun isForeground(context: Context?): Boolean {
        if (context != null) {
            val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val processes = am.runningAppProcesses
            for (processInfo in processes) {
                if (processInfo.processName == context.packageName) {
                    if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                        return true
                    }
                }
            }
        }
        return false
    }

    /**
     * 判断B应用是否在后台运行并直接打开
     * 如果当次设备
     */
    private fun openPackage(context: Context, packageName: String): Boolean {
        val pkgContext = getPackageContext(context, packageName)
        val intent = PullUpUtils.getAppOpenIntentByPackageName(context, packageName)
        if (pkgContext != null && intent != null) {
            pkgContext.startActivity(intent)
            return true
        }
        return false
    }

    /**
     * 判断应用是否在运行中
     */
    private fun isRun(context: Context, packageName: String): Boolean {
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val list = am.getRunningTasks(100)
        var isAppRunning = false

        //100表示取的最大的任务数，info.topActivity表示当前正在运行的Activity，info.baseActivity表系统后台有此进程在运行
        for (info in list) {
            if (info.topActivity!!.packageName == packageName || info.baseActivity!!.packageName == packageName) {
                isAppRunning = true
                break
            }
        }
        return isAppRunning
    }

    /**
     * 获取程序B的上下文Context
     */
    private fun getPackageContext(context: Context, packageName: String): Context? {
        var pkgContext: Context? = null
        if (context.packageName == packageName) {
            pkgContext = context
        } else {
            // 创建第三方应用的上下文环境
            try {
                pkgContext = context.createPackageContext(
                    packageName, Context.CONTEXT_IGNORE_SECURITY or Context.CONTEXT_INCLUDE_CODE
                )
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
            }
        }
        return pkgContext
    }

    /**
     * 拉起其他的App
     */
    fun pullApp(context: Context, pkgName: String): Boolean {
        //1. 判断程序B是否存在
        return if (checkPackInfo(pkgName, context)) {
            //2.判断程序B是否在前台运行
            val pkgContext = getPackageContext(context, pkgName)
            val isForeground = isForeground(pkgContext)
            //3. 判断B是否在前台，如果是就不启动
            if (!isForeground) {
                //1. 启动方式1
                return openPackage(context, pkgName)
            } else {
                //已经在前台运行中，不用在拉起了
                true
            }
        } else {
            Toast.makeText(context, "需要拉起的软件还未安装,请先下载!", Toast.LENGTH_LONG).show()
            false
        }
    }

    /**
     * 获取手机已安装应用列表
     * @param ctx
     * @param isFilterSystem 是否过滤系统应用
     * @return
     */
    fun getAllAppInfo(
        ctx: Context,
        isFilterSystem: Boolean
    ): ArrayList<AppInfo>? {
        val appBeanList: ArrayList<AppInfo> = ArrayList()
        try {
            var bean: AppInfo? = null
            val packageManager = ctx.packageManager
            val list = packageManager.getInstalledPackages(0)
            for (p in list) {
                bean = AppInfo()
                bean.setLabel(packageManager.getApplicationLabel(p.applicationInfo).toString())
                bean.setPackage_name(p.applicationInfo.packageName)
                val flags = p.applicationInfo.flags
                // 判断是否是属于系统的apk
                if (flags and ApplicationInfo.FLAG_SYSTEM != 0 && isFilterSystem) {
                    Log.d(TAG, "getAllAppInfo 系统app")
                } else {
                    appBeanList.add(bean)
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, e.toString())
        }
        return appBeanList
    }

    /**
     * 获取指定目录内所有文件路径
     * @param dirPath 需要查询的文件目录
     * @param type 查询类型，比如mp3什么的
     */
    fun getAllFiles(dirPath: String, type: String): JSONArray? {
        val f = File(dirPath)
        if (!f.exists()) { //判断路径是否存在
            return null
        }
        val files = f.listFiles()
            ?: //判断权限
            return null
        val fileList = JSONArray()
        for (file in files) { //遍历目录
            if (file.isFile && file.name.endsWith(type!!)) {
                val name = file.name
                val filePath = file.absolutePath //获取文件路径
                val fileName = file.name.substring(0, name.length - 4) //获取文件名
                try {
                    val fInfo = JSONObject()
                    fInfo.put("name", fileName)
                    fInfo.put("path", filePath)
                    fileList.put(fInfo)
                } catch (e: Exception) {
                }
            } else if (file.isDirectory) { //查询子目录
                getAllFiles(file.absolutePath, type)
            } else {
            }
        }
        return fileList
    }

    /**
     * 获取后台运行APP packageName
     * @param context
     */
    fun getRunningApp(context: Context): MutableList<String> {
        val packageList: MutableList<String> = ArrayList()
        val localPackageManager = context.packageManager
        val localList = localPackageManager.getInstalledPackages(0)
        for (i in localList.indices) {
            val localPackageInfo = localList[i] as PackageInfo
            val packageStr = localPackageInfo.packageName.split(":").toTypedArray()[0]
            if (ApplicationInfo.FLAG_SYSTEM and localPackageInfo.applicationInfo.flags == 0
                && ApplicationInfo.FLAG_UPDATED_SYSTEM_APP and localPackageInfo.applicationInfo.flags == 0
                && ApplicationInfo.FLAG_STOPPED and localPackageInfo.applicationInfo.flags == 0
            ) {
                packageList.add(packageStr)
                Log.d("TAG", packageStr)
            }
        }
        return packageList
    }

    companion object {
        private var appUtil: AppUtil? = null
        val instance: AppUtil
            get() {
                if (appUtil == null) {
                    appUtil = AppUtil()
                }
                return appUtil!!
            }
    }
}